#pragma once

#include "opencv2/myopencv.hpp"
#include <fstream>
#include <iostream>
using namespace std;

typedef struct CvPointList {
	int length;
	CvPoint* data;
} CvPointList;
typedef struct CvPointListList {
	int length;
	CvPointList** lists;
} CvPointListList;

//only support 3 channel
typedef struct CvScalarI {
	const uchar* val;
	int data[3];

	CvScalarI operator + (const CvScalarI& src) const {
		CvScalarI res;
		for (int i=0; i<3; ++i)
			res.data[i] = this->data[i] + src.data[i];
		res.val = NULL;
		return res;
	}

	CvScalarI operator - (const CvScalarI& src2) const {
		CvScalarI res;
		for (int i=0; i<3; ++i)
			res.data[i] = this->data[i] - src2.data[i];
		res.val = NULL;
		return res;
	}

	CvScalar operator - (const CvScalar& src2) const {
		CvScalar res = cvScalar(0);
		for (int i=0; i<3; ++i)
			res.val[i] = this->data[i] - src2.val[i];
		return res;
	}

	CvScalarI& operator ++() {//prefix
		if (val == NULL)
			for (int i=0; i<3; ++i)
				data[i] = -1;
		else {
			val += 3;
			for (int i=0; i<3; ++i)
				data[i] = *(val+i);
		}
		return *this;
	}

	const CvScalarI operator ++(int) {//postfix
		++(*this);
		return *this;
	}

	bool operator == (const CvScalarI& src) const {
		for (int i=0; i<3; ++i)
			if (this->data[i] != src.data[i]) return false;
		return true;
	}

	CvScalarI operator * (int sca) const {
		CvScalarI res;
		for (int i=0; i<3; ++i)
			res.data[i] = sca * this->data[i];
		res.val = NULL;
		return res;
	}

	CvScalar operator * (double sca) const {
		CvScalar res = cvScalar(0);
		for (int i=0; i<3; ++i)
			res.val[i] = sca * this->data[i];
		return res;
	}

	CvScalarI operator / (int sca) const {
		CvScalarI res;
		for (int i=0; i<3; ++i)
			res.data[i] = this->data[i] / sca;
		res.val = NULL;
		return res;
	}

} CvScalarI;
CvScalarI cvScalarI(uchar* ptr);
CvScalarI cvScalarI(void);
CvScalarI cvScalarI(CvScalar s);

void cvShowRGB(CvScalar sca);

void cvPrintMat(CvMat* mat, ostream* out CV_DEFAULT(&cout), bool bgr CV_DEFAULT(false));
void cvPrintMat(CvMat* mat, char filename[], bool bgr CV_DEFAULT(false));
CvMat *cvLoadMat(char filename[], int cn CV_DEFAULT(1), bool isUchar CV_DEFAULT(false));
void debugByMouseDb(int type, int x, int y, int flag, void* param);
void debugByMouseCh(int type, int x, int y, int flag, void* param);
CvMat* cvRgb2gray(CvMat* img);
//only return double
CvMat* cvDivide (CvMat *a, double b);
//only return uchar
CvMat* cvMul2 (const uchar scale, const CvMat* src);
//only return double
CvMat* cvMul2(CvMat* inSrc1, CvMat* inSrc2, CvMat *dst CV_DEFAULT(NULL), int retType CV_DEFAULT(CV_64F));
CvMat* cvIm2double(CvMat* img);
CvMat* cvConvertMatType(CvMat* src, int type);
void cvSaveRawImg(char filename[], CvMat *img);
void cvSaveMatImage(char filename[], CvMat *mat);

//return mat type without depth information
inline int cvMatElementType(CvMat *src);
//return mat type with depth information
inline int cvMatType(CvMat *src);
//the label must less than 254. The src image will be changed.
CvPointListList cvBwlabel(CvMat *src);

void cvMinMaxLoc(CvMat *src, CvPointList plist, double &minVal, double &maxVal);
void cvMinMaxLoc(CvMat *src, CvPointList plist, double &minVal, double &maxVal,
				 int &minIdx, int &maxIdx);

void cvShowHist(CvHistogram *pHist, char *winName=NULL, int binW=20);
inline int cvFitIn(int x, int a, int b);

CvHistogram operator - (CvHistogram& a, CvHistogram& b);

#ifdef _DEBUG
#pragma comment(lib, "augmentopencvd.lib")
#else
#pragma comment(lib, "augmentopencv.lib")
#endif